#include "xmlhelper.h"
#include "tinyxml2/tinyxml2.h"

#define BUF_SIZE	128


/************************************************
 * 功能：构造函数
 * ***********************************************/
XmlHelper::XmlHelper()
#if 0
    : m_strXmlFilePath("")
    , m_spDoc(nullptr)
    , m_pCurElement(nullptr)
    #endif
{
    if (!m_spDoc) {
        m_spDoc = std::make_shared<tinyxml2::XMLDocument>();
    }
}

/************************************************
 * 功能：析构函数
 * ***********************************************/
XmlHelper::~XmlHelper()
{
    clear();

    if (m_spDoc) {
        m_spDoc.reset();
        m_spDoc = nullptr;
    }
}

/************************************************
 * 功能：重置和清空xml内容
 * ***********************************************/
void XmlHelper::clear()
{
    if (m_spDoc) {
        m_spDoc->Clear();
    }
    return;
}

/************************************************
 * 功能：保存xml文件
 * 返回值：
 *      bool：操作结果，true -- 成功，false -- 失败
 * ***********************************************/
bool XmlHelper::saveXmlFile()
{
    bool bRet = false;
    if (!m_strXmlFilePath.empty() && m_spDoc) {
        bRet = (tinyxml2::XML_SUCCESS == m_spDoc->SaveFile(m_strXmlFilePath.c_str())) ? true : false;
    }
    return bRet;
}

/************************************************
 * 功能：解析xml文件
 * 注：自动进入root节点
 * 输入参数：
 *      strXmlContent：xml内容
 * 返回值：
 *      bool：操作结果，true -- 成功，false -- 失败
 * ***********************************************/
bool XmlHelper::parseXmlContent(const std::string &strXmlContent)
{
    bool bRet = false;
    clear();
    if (!strXmlContent.empty() && m_spDoc) {
        bRet = (tinyxml2::XML_SUCCESS == m_spDoc->Parse(strXmlContent.c_str(), strXmlContent.length())) ? true : false;
        // 加载后自动进入根节点
        if (bRet) {
            m_pCurElement = m_spDoc->RootElement();
        }
    }
    return bRet;
}

/************************************************
 * 功能：获取xml文件中的xml内容
 * 输入参数：
 *      strXmlFilePath：xml文件路径
 * 返回值：
 *      std::string：xml内容
 * ***********************************************/
std::string XmlHelper::getXmlFileContent(const std::string &strXmlFilePath)
{
    std::string strFileContent = "";
    if (loadXmlFile(strXmlFilePath)) {
        strFileContent = getXmlContent();
    }
    return strFileContent;
}

/************************************************
 * 功能：获取当前DOC中的xml内容
 * 返回值：
 *      std::string：xml内容
 * ***********************************************/
std::string XmlHelper::getXmlContent()
{
    std::string strFileContent = "";
    if (m_spDoc) {
        tinyxml2::XMLPrinter objPrinter;
        m_spDoc->Print(&objPrinter);
        strFileContent = objPrinter.CStr();
    }
    return strFileContent;
}

/************************************************
 * 功能：创建xml文件
 * 注：自动进入root节点
 * 输入参数：
 *      strXmlFilePath：xml文件路径
 *      strRootName：根节点名称
 * 返回值：
 *      bool：操作结果，true -- 成功，false -- 失败
 * ***********************************************/
bool XmlHelper::createXmlFilePath(const std::string &strXmlFilePath, const std::string &strRootName)
{
    bool bRet = false;

    m_strXmlFilePath = strXmlFilePath;
    if (!m_strXmlFilePath.empty() && m_spDoc) {
        tinyxml2::XMLError eError = m_spDoc->LoadFile(m_strXmlFilePath.c_str());
        bRet = (tinyxml2::XML_ERROR_FILE_NOT_FOUND == eError) ? true : false;
#if 0
        if (tinyxml2::XML_ERROR_FILE_NOT_FOUND == eError) {
            eError = m_spDoc->SaveFile(m_strXmlFilePath.c_str());
            if (tinyxml2::XML_SUCCESS == eError) {
                eError = m_spDoc->LoadFile(m_strXmlFilePath.c_str());
            }
        }
        bRet = (tinyxml2::XML_ERROR_EMPTY_DOCUMENT == eError) ? true : false;
#endif
    }

    if (bRet && m_spDoc) {
        // 插入XML头信息
        tinyxml2::XMLDeclaration *pDeclare = m_spDoc->NewDeclaration();
        if (pDeclare) {
            m_spDoc->InsertFirstChild(pDeclare);
        }
        // 插入根节点
        m_pCurElement = m_spDoc->NewElement(strRootName.c_str());
        if (m_pCurElement) {
            m_spDoc->InsertEndChild(m_pCurElement);
        }
    }

    return bRet;
}

/************************************************
 * 功能：加载并读入xml文件
 * 注：自动进入root节点
 * 输入参数：
 *      strXmlFilePath：xml文件路径
 * 返回值：
 *      bool：操作结果，true -- 成功，false -- 失败
 * ***********************************************/
bool XmlHelper::loadXmlFile(const std::string &strXmlFilePath)
{
    bool bRet = false;

    m_strXmlFilePath = strXmlFilePath;
    if (!m_strXmlFilePath.empty() && m_spDoc) {
        bRet = (tinyxml2::XML_SUCCESS == m_spDoc->LoadFile(m_strXmlFilePath.c_str())) ? true : false;
    }

    // 加载后自动进入根节点
    if (bRet && m_spDoc) {
        m_pCurElement = m_spDoc->RootElement();
    }

    return bRet;
}

/************************************************
 * 功能：定位到根节点位置
 * ***********************************************/
void XmlHelper::beginRootElement()
{
    if (m_spDoc) {
        m_pCurElement = m_spDoc->RootElement();
    }
    return;
}

/************************************************
 * 功能：获取当前节点的名称标识
 * 返回值：
 *      std::string：当前节点名称标识
 * ***********************************************/
std::string XmlHelper::currentElemName()
{
    std::string strRet = "";
    if (m_pCurElement) {
        const char *pRet = m_pCurElement->Name();
        if (pRet) {
            strRet = std::string(pRet);
        }
    }
    return strRet;
}

/************************************************
 * 功能：获取当前节点的内容值
 * 返回值：
 *      std::string：当前节点内容值
 * ***********************************************/
std::string XmlHelper::currentElemText()
{
    std::string strRet = "";
    if (m_pCurElement) {
        const char *pRet = m_pCurElement->GetText();
        if (pRet) {
            strRet = std::string(pRet);
        }
    }
    return strRet;
}

/************************************************
 * 功能：判断当前节点中是否存在指定名称的子节点
 * 输入参数：
 *      strName：子节点的名称标识
 * 返回值：
 *      bool：判断结果，true -- 存在，false -- 不存在
 * ***********************************************/
bool XmlHelper::hasChildElement(const std::string &strName)
{
    bool bRet = false;
    if (!strName.empty() && m_pCurElement && m_pCurElement->FirstChildElement(strName.c_str())) {
        bRet = true;
    }
    return bRet;
}

/************************************************
 * 功能：当前节点中定位到指定名称个子节点
 * 输入参数：
 *      strName：子节点的名称标识
 * ***********************************************/
void XmlHelper::beginChildElement(const std::string &strName)
{
    if (m_pCurElement) {
        tinyxml2::XMLElement *pElement = m_pCurElement->FirstChildElement(strName.c_str());
        if (!pElement && m_spDoc) {
            pElement = m_spDoc->NewElement(strName.c_str());
            if (pElement) {
                m_pCurElement->InsertEndChild(pElement);
            }
        }

        if (pElement) {
            m_pCurElement = pElement;
        }
    }
    return;
}

/************************************************
 * 功能：当前节点中定位到指定子节点
 * 输入参数：
 *      pElement：子节点的指针
 * ***********************************************/
void XmlHelper::beginElement(tinyxml2::XMLElement *pElement)
{
    if (pElement) {
        m_pCurElement = pElement;
    }
    return;
}

/************************************************
 * 功能：结束当前节点到其父节点位置
 * ***********************************************/
void XmlHelper::endElement()
{
    if (m_pCurElement) {
        if (m_pCurElement->Parent()) {
            m_pCurElement = m_pCurElement->Parent()->ToElement();
        } else {
            m_pCurElement = nullptr;
        }
    }
    return;
}

/************************************************
 * 功能：从当前节点中添加指定名称的子节点
 * 输入参数：
 *      strName：子节点的名称标识
 * 返回值：
 *      tinyxml2::XMLElement*：子节点的指针
 * ***********************************************/
tinyxml2::XMLElement* XmlHelper::addChildElement(const std::string &strName)
{
    tinyxml2::XMLElement *pElement = nullptr;
    if (!strName.empty() && m_spDoc) {
        pElement = m_spDoc->NewElement(strName.c_str());
        if (pElement && m_pCurElement) {
            m_pCurElement->InsertEndChild(pElement);
        }
    }
    return pElement;
}

/************************************************
 * 功能：从当前节点中删除所有指定名称的子节点
 * 输入参数：
 *      strName：子节点的名称标识
 * ***********************************************/
void XmlHelper::deleteChildElement(const std::string &strName)
{
    if (!strName.empty()) {
        tinyxml2::XMLElement *pElement = m_pCurElement->LastChildElement(strName.c_str());
        while (pElement) {
            m_pCurElement->DeleteChild(pElement);
            pElement = m_pCurElement->LastChildElement(strName.c_str());
        }
    }
    return;
}

/************************************************
 * 功能：获取当前节点中所有指定名称的子节点，一般用于操作xml中的list节点
 * 输入参数：
 *      strName：子节点的名称标识
 * 返回值：
 *      std::list<tinyxml2::XMLElement *>：子节点集合
 * ***********************************************/
std::list<tinyxml2::XMLElement *> XmlHelper::childElements(const std::string &strName)
{
    if (strName.empty()) {
        std::list<tinyxml2::XMLElement *> lstEmpty;
        return lstEmpty;
    }

    std::list<tinyxml2::XMLElement *> lstElements;
    lstElements.clear();

    if (m_pCurElement) {
        tinyxml2::XMLElement *pElement = m_pCurElement->FirstChildElement();
        while (pElement) {
            if (0 == strName.compare(pElement->Name())) {
                lstElements.emplace_back(pElement);
            }
            pElement = pElement->NextSiblingElement();
        }
    }

    return lstElements;
}

/************************************************
 * 功能：获取当前节点中所有指定名称的子节点，一般用于操作xml中的list节点
 * 输入参数：
 *      strName：子节点的名称标识
 * 返回值：
 *      std::list<tinyxml2::XMLElement *>：子节点集合
 * ***********************************************/
void XmlHelper::childElements(const std::string &strName, std::list<tinyxml2::XMLElement *> lstElements)
{
    if (strName.empty()) {
        return;
    }

    lstElements.clear();
    if (m_pCurElement) {
        tinyxml2::XMLElement *pElement = m_pCurElement->FirstChildElement();
        while (pElement) {
            if (0 == strName.compare(pElement->Name())) {
                lstElements.emplace_back(pElement);
            }
            pElement = pElement->NextSiblingElement();
        }
    }
    return;
}

/************************************************
 * 功能：获取当前节点中所有指定名称的子节点，一般用于操作xml中的list节点
 * 输入参数：
 *      strName：子节点的名称标识
 * 输出参数：
 *      vtElements：子节点集合
 * ***********************************************/
void XmlHelper::childElements(const std::string &strName, std::vector<tinyxml2::XMLElement *> vtElements)
{
    if (strName.empty()) {
        return;
    }

    vtElements.clear();
    if (m_pCurElement) {
#if 0
        tinyxml2::XMLElement *pElement = m_pCurElement->FirstChildElement();
        while (pElement) {
            if (0 == strName.compare(pElement->Name())) {
                vtElements.emplace_back(pElement);
            }
            pElement = pElement->NextSiblingElement();
        }
#else
        tinyxml2::XMLElement *pElement = m_pCurElement->FirstChildElement(strName.data());
        while (pElement) {
            vtElements.emplace_back(pElement);
            pElement = pElement->NextSiblingElement(strName.data()); // 同级往下
        }
#endif
    }
    return;
}

/************************************************
 * 功能：设置当前节点的内容值，字符串类型数据
 * 输入参数：
 *      pText：节点的内容值
 * ***********************************************/
void XmlHelper::setText(const char *pText)
{
    if (pText && m_pCurElement) {
        m_pCurElement->SetText(pText);
    }
    return;
}

/************************************************
 * 功能：设置当前节点的内容值，字符串类型数据
 * 输入参数：
 *      strText：节点的内容值
 * ***********************************************/
void XmlHelper::setText(const std::string &strText)
{
    if (strText.empty()) {
        return;
    }

    if (m_pCurElement) {
        m_pCurElement->SetText(strText.c_str());
    }
    return;
}

/************************************************
 * 功能：设置当前节点的内容值，int类型数据
 * 输入参数：
 *      iText：节点的内容值
 * ***********************************************/
void XmlHelper::setText(int iText)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(iText, szBuf, BUF_SIZE);
    setText(std::string(szBuf));
    return;
}

/************************************************
 * 功能：设置当前节点的内容值，double类型数据
 * 输入参数：
 *      dText：节点的内容值
 * ***********************************************/
void XmlHelper::setText(double dText)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(dText, szBuf, BUF_SIZE);
    setText(std::string(szBuf));
    return;
}

/************************************************
 * 功能：设置当前节点的内容值，bool类型数据
 * 输入参数：
 *      bText：子节点的内容值
 * ***********************************************/
void XmlHelper::setText(bool bText)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(bText, szBuf, BUF_SIZE);
    setText(std::string(szBuf));
    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点的内容值，字符串类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      pText：子节点的内容值
 * ***********************************************/
void XmlHelper::setChildText(const std::string &strName, const char *pText)
{
    if (strName.empty() || !pText) {
        return;
    }

    if (m_pCurElement) {
        tinyxml2::XMLElement *pElement = m_pCurElement->LastChildElement(strName.c_str());
        if (pElement) {
            pElement->SetText(pText);
        } else {
            if (m_spDoc) {
                tinyxml2::XMLElement *pElement = m_spDoc->NewElement(strName.c_str());
                tinyxml2::XMLText *pXmlText = m_spDoc->NewText(pText);
                if (pElement && pXmlText) {
                    pElement->InsertFirstChild(pXmlText);
                    m_pCurElement->InsertEndChild(pElement);
                }
            }
        }
    }

    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点的内容值，字符串类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      strText：子节点的内容值
 * ***********************************************/
void XmlHelper::setChildText(const std::string &strName, const std::string &strText)
{
    if (strName.empty()) {
        return;
    }

    if (m_pCurElement) {
        tinyxml2::XMLElement *pElement = m_pCurElement->LastChildElement(strName.c_str());
        if (pElement) {
            pElement->SetText(strText.c_str());
        } else {
            if (m_spDoc) {
                tinyxml2::XMLElement *pElement = m_spDoc->NewElement(strName.c_str());
                tinyxml2::XMLText *pText = m_spDoc->NewText(strText.c_str());
                if (pElement && pText) {
                    pElement->InsertFirstChild(pText);
                    m_pCurElement->InsertEndChild(pElement);
                }
            }
        }
    }

    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点的内容值，int类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      iText：子节点的内容值
 * ***********************************************/
void XmlHelper::setChildText(const std::string &strName, int iText)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(iText, szBuf, BUF_SIZE);
    setChildText(strName, std::string(szBuf));
    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点的内容值，double类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      dText：子节点的内容值
 * ***********************************************/
void XmlHelper::setChildText(const std::string &strName, double dText)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(dText, szBuf, BUF_SIZE);
    setChildText(strName, std::string(szBuf));
    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点的内容值，bool类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      bText：子节点的内容值
 * ***********************************************/
void XmlHelper::setChildText(const std::string &strName, bool bText)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(bText, szBuf, BUF_SIZE);
    setChildText(strName, std::string(szBuf));
    return;
}

/************************************************
 * 功能：获取当前节点的内容值，字符串类型数据
 * 返回值：
 *      std::string：节点的内容值
 * ***********************************************/
std::string XmlHelper::text()
{
    std::string strRet = "";
    if (m_pCurElement) {
        const char *pRet = m_pCurElement->GetText();
        if (pRet) {
            strRet = std::string(pRet);
        }
    }
    return strRet;
}

/************************************************
 * 功能：获取当前节点的内容值，int类型数据
 * 返回值：
 *      int：节点的内容值
 * ***********************************************/
int XmlHelper::intText()
{
    std::string strRet = text();
    int iRet = 0;
    tinyxml2::XMLUtil::ToInt(strRet.c_str(), &iRet);
    return iRet;
}

/************************************************
 * 功能：获取当前节点的内容值，double类型数据
 * 返回值：
 *      double：节点的内容值
 * ***********************************************/
double XmlHelper::doubleText()
{
    std::string strRet = text();
    double dRet = 0;
    tinyxml2::XMLUtil::ToDouble(strRet.c_str(), &dRet);
    return dRet;
}

/************************************************
 * 功能：获取当前节点的内容值，bool类型数据
 * 返回值：
 *      bool：节点的内容值
 * ***********************************************/
bool XmlHelper::boolText()
{
    std::string strRet = text();
    bool bRet = false;
    tinyxml2::XMLUtil::ToBool(strRet.c_str(), &bRet);
    return bRet;
}

/************************************************
 * 功能：获取当前节点中指定名称子节点的内容值，字符串类型数据
 * 输入参数：
 *      strName：子节点的名称标识
 * 返回值：
 *      std::string：子节点的内容值
 * ***********************************************/
std::string XmlHelper::childText(const std::string &strName)
{
    std::string strRet = "";
    if (!strName.empty()) {
        if (m_pCurElement) {
            tinyxml2::XMLElement *pElement = m_pCurElement->LastChildElement(strName.c_str());
            if (pElement){
                const char *pRet = pElement->GetText();
                if (pRet) {
                    strRet = std::string(pRet);
                }
            }
        }
    }
    return strRet;
}

/************************************************
 * 功能：获取当前节点中指定名称子节点的内容值，int类型数据
 * 输入参数：
 *      strName：子节点的名称标识
 * 返回值：
 *      int：子节点的内容值
 * ***********************************************/
int XmlHelper::childIntText(const std::string &strName)
{
    std::string strRet = childText(strName);
    int iRet = 0;
    tinyxml2::XMLUtil::ToInt(strRet.c_str(), &iRet);
    return iRet;
}

/************************************************
 * 功能：获取当前节点中指定名称子节点的内容值，double类型数据
 * 输入参数：
 *      strName：子节点的名称标识
 * 返回值：
 *      double：子节点的内容值
 * ***********************************************/
double XmlHelper::childDoubleText(const std::string &strName)
{
    std::string strRet = childText(strName);
    double dRet = 0;
    tinyxml2::XMLUtil::ToDouble(strRet.c_str(), &dRet);
    return dRet;
}

/************************************************
 * 功能：获取当前节点中指定名称子节点的内容值，bool类型数据
 * 输入参数：
 *      strName：子节点的名称标识
 * 返回值：
 *      bool：子节点的内容值
 * ***********************************************/
bool XmlHelper::childBoolText(const std::string &strName)
{
    std::string strRet = childText(strName);
    bool bRet = false;
    tinyxml2::XMLUtil::ToBool(strRet.c_str(), &bRet);
    return bRet;
}

/************************************************
 * 功能：为当前节点设置指定属性的值，字符串类型数据
 * 输入参数：
 *      strAttributeName：当前节点的指定属性名称标识
 *      pValue：当前节点的指定属性的值
 * ***********************************************/
void XmlHelper::setAttribute(const std::string &strAttributeName, const char *pValue)
{
    if (!strAttributeName.empty() && pValue && m_pCurElement) {
        m_pCurElement->SetAttribute(strAttributeName.c_str(), pValue);
    }
    return;
}

/************************************************
 * 功能：为当前节点设置指定属性的值，字符串类型数据
 * 输入参数：
 *      strAttributeName：当前节点的指定属性名称标识
 *      strValue：当前节点的指定属性的值
 * ***********************************************/
void XmlHelper::setAttribute(const std::string &strAttributeName, const std::string &strValue)
{
    if (strAttributeName.empty() || strValue.empty()) {
        return;
    }

    if (m_pCurElement) {
        m_pCurElement->SetAttribute(strAttributeName.c_str(), strValue.c_str());
    }
    return;
}

/************************************************
 * 功能：为当前节点设置指定属性的值，int类型数据
 * 输入参数：
 *      strAttributeName：当前节点的指定属性名称标识
 *      iValue：当前节点的指定属性的值
 * ***********************************************/
void XmlHelper::setAttribute(const std::string &strAttributeName, int iValue)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(iValue, szBuf, BUF_SIZE);
    setAttribute(strAttributeName, std::string(szBuf));
    return;
}

/************************************************
 * 功能：为当前节点设置指定属性的值，double类型数据
 * 输入参数：
 *      strAttributeName：当前节点的指定属性名称标识
 *      dValue：当前节点的指定属性的值
 * ***********************************************/
void XmlHelper::setAttribute(const std::string &strAttributeName, double dValue)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(dValue, szBuf, BUF_SIZE);
    setAttribute(strAttributeName, std::string(szBuf));
    return;
}

/************************************************
 * 功能：为当前节点设置指定属性的值，bool类型数据
 * 输入参数：
 *      strAttributeName：当前节点的指定属性名称标识
 *      bValue：当前节点的指定属性的值
 * ***********************************************/
void XmlHelper::setAttribute(const std::string &strAttributeName, bool bValue)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(bValue, szBuf, BUF_SIZE);
    setAttribute(strAttributeName, std::string(szBuf));
    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点指定属性的值，字符串类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 *      pVal：子节点的指定属性的值
 * ***********************************************/
void XmlHelper::setChildAttribute(const std::string &strName, const std::string &strAttributeName, const char *pVal)
{
    if (strName.empty() || strAttributeName.empty() || !pVal) {
        return;
    }

    if (m_pCurElement) {
        tinyxml2::XMLElement *pElement = m_pCurElement->LastChildElement(strName.c_str());
        if (pElement) {
            pElement->SetAttribute(strAttributeName.c_str(), pVal);
        } else {
            if (m_spDoc) {
                tinyxml2::XMLElement *pElement = m_spDoc->NewElement(strName.c_str());
                if (pElement) {
                    pElement->SetAttribute(strAttributeName.c_str(), pVal);
                    m_pCurElement->InsertEndChild(pElement);
                }
            }
        }
    }
    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点指定属性的值，字符串类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 *      strValue：子节点的指定属性的值
 * ***********************************************/
void XmlHelper::setChildAttribute(const std::string &strName, const std::string &strAttributeName, const std::string &strValue)
{
    if (strName.empty() || strAttributeName.empty() || strValue.empty()) {
        return;
    }

    if (m_pCurElement) {
        tinyxml2::XMLElement *pElement = m_pCurElement->LastChildElement(strName.c_str());
        if (pElement) {
            pElement->SetAttribute(strAttributeName.c_str(), strValue.c_str());
        } else {
            if (m_spDoc) {
                tinyxml2::XMLElement *pElement = m_spDoc->NewElement(strName.c_str());
                if (pElement) {
                    pElement->SetAttribute(strAttributeName.c_str(), strValue.c_str());
                    m_pCurElement->InsertEndChild(pElement);
                }
            }
        }
    }
    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点指定属性的值，int类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 *      iValue：子节点的指定属性的值
 * ***********************************************/
void XmlHelper::setChildAttribute(const std::string &strName, const std::string &strAttributeName, int iValue)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(iValue, szBuf, BUF_SIZE);
    setChildAttribute(strName, strAttributeName, std::string(szBuf));
    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点指定属性的值，double类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 *      dValue：子节点的指定属性的值
 * ***********************************************/
void XmlHelper::setChildAttribute(const std::string &strName, const std::string &strAttributeName, double dValue)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(dValue, szBuf, BUF_SIZE);
    setChildAttribute(strName, strAttributeName, std::string(szBuf));
    return;
}

/************************************************
 * 功能：设置当前节点中指定名称子节点指定属性的值，bool类型数据
 * 注：最后一个子节点名不匹配时，创建/追加子节点
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 *      bValue：子节点的指定属性的值
 * ***********************************************/
void XmlHelper::setChildAttribute(const std::string &strName, const std::string &strAttributeName, bool bValue)
{
    char szBuf[BUF_SIZE] = { 0 };
    tinyxml2::XMLUtil::ToStr(bValue, szBuf, BUF_SIZE);
    setChildAttribute(strName, strAttributeName, std::string(szBuf));
    return;
}

/************************************************
 * 功能：删除当前节点中指定属性标识
 * 输入参数：
 *      strAttributeName：当前节点的指定属性名称标识
 * ***********************************************/
void XmlHelper::deleteAttribute(const std::string &strAttributeName)
{
    if (strAttributeName.empty()) {
        return;
    }

    if (m_pCurElement) {
        m_pCurElement->DeleteAttribute(strAttributeName.c_str());
    }

    return;
}

/************************************************
 * 功能：删除当前节点中指定名称子节点指定属性标识
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 * ***********************************************/
void XmlHelper::deleteChildAttribute(const std::string &strName, const std::string &strAttributeName)
{
#if 0
    do
    {
        if (strName.empty() || strAttributeName.empty())
        {
            break;
        }

        if (m_pCurElement)
        {
            tinyxml2::XMLElement *pElement = m_pCurElement->LastChildElement(strName.c_str());
            if (pElement)
            {
                pElement->DeleteAttribute(strAttributeName.c_str());
            }
        }

    } while (0);
#else
    if (strName.empty() || strAttributeName.empty()) {
        return;
    }

    if (m_pCurElement) {
        tinyxml2::XMLElement *pElement = m_pCurElement->LastChildElement(strName.c_str());
        if (pElement) {
            pElement->DeleteAttribute(strAttributeName.c_str());
        }
    }
#endif
    return;
}

/************************************************
 * 功能：获取当前节点中指定属性标识的值，字符串类型
 * 返回值：
 *      std::string：当前节点的指定属性的字符串值
 * ***********************************************/
std::string XmlHelper::attribute(const std::string &strAttributeName)
{
    if (strAttributeName.empty()) {
        return "";
    }

    std::string strRet = "";
    if (m_pCurElement) {
        const char *pRet = m_pCurElement->Attribute(strAttributeName.c_str());
        if (pRet) {
            strRet = std::string(pRet);
        }
    }
    return strRet;
}

/************************************************
 * 功能：获取当前节点中指定属性标识的值，int类型
 * 输入参数：
 *      strAttributeName：当前节点的指定属性名称标识
 * 返回值：
 *      int：当前节点的指定属性的int值
 * ***********************************************/
int XmlHelper::intAttribute(const std::string &strAttributeName)
{
    std::string strRet = attribute(strAttributeName);
    int iRet = 0;
    tinyxml2::XMLUtil::ToInt(strRet.c_str(), &iRet);
    return iRet;
}

/************************************************
 * 功能：获取当前节点中指定属性标识的值，double类型
 * 输入参数：
 *      strAttributeName：当前节点的指定属性名称标识
 * 返回值：
 *      double：当前节点的指定属性的double值
 * ***********************************************/
double XmlHelper::doubleAttribute(const std::string &strAttributeName)
{
    std::string strRet = attribute(strAttributeName);
    double dRet = 0;
    tinyxml2::XMLUtil::ToDouble(strRet.c_str(), &dRet);
    return dRet;
}

/************************************************
 * 功能：获取当前节点中指定属性标识的值，bool类型
 * 输入参数：
 *      strAttributeName：当前节点的指定属性名称标识
 * 返回值：
 *      bool：当前节点的指定属性的bool值
 * ***********************************************/
bool XmlHelper::boolAttribute(const std::string &strAttributeName)
{
    std::string strRet = attribute(strAttributeName);
    bool bRet = false;
    tinyxml2::XMLUtil::ToBool(strRet.c_str(), &bRet);
    return bRet;
}

/************************************************
 * 功能：获取当前节点中指定名称子节点指定属性标识的值，字符串类型
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 * 返回值：
 *      std::string：子节点的指定属性的字符串值
 * ***********************************************/
std::string XmlHelper::childAttribute(const std::string &strName, const std::string &strAttributeName)
{
    if (strName.empty() || strAttributeName.empty()) {
        return "";
    }

    std::string strRet = "";
    if (m_pCurElement) {
        tinyxml2::XMLElement *pElement = m_pCurElement->LastChildElement(strName.c_str());
        if (pElement) {
            const char *pRet = pElement->Attribute(strAttributeName.c_str());
            if (pRet) {
                strRet = std::string(pRet);
            }
        }
    }
    return strRet;
}

/************************************************
 * 功能：获取当前节点中指定名称子节点指定属性标识的值，int类型
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 * 返回值：
 *      int：子节点的指定属性的int值
 * ***********************************************/
int XmlHelper::childIntAttribute(const std::string &strName, const std::string &strAttributeName)
{
    std::string strRet = childAttribute(strName, strAttributeName);
    int iRet = 0;
    tinyxml2::XMLUtil::ToInt(strRet.c_str(), &iRet);
    return iRet;
}

/************************************************
 * 功能：获取当前节点中指定名称子节点指定属性标识的值，double类型
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 * 返回值：
 *      double：子节点的指定属性的double值
 * ***********************************************/
double XmlHelper::childDoubleAttribute(const std::string &strName, const std::string &strAttributeName)
{
    std::string strRet = childAttribute(strName, strAttributeName);
    double dRet = 0;
    tinyxml2::XMLUtil::ToDouble(strRet.c_str(), &dRet);
    return dRet;
}

/************************************************
 * 功能：获取当前节点中指定名称子节点指定属性标识的值，bool类型
 * 输入参数：
 *      strName：子节点的名称标识
 *      strAttributeName：子节点的指定属性名称标识
 * 返回值：
 *      bool：子节点的指定属性的bool值
 * ***********************************************/
bool XmlHelper::childBoolAttribute(const std::string &strName, const std::string &strAttributeName)
{
    std::string strRet = childAttribute(strName, strAttributeName);
    bool bRet = false;
    tinyxml2::XMLUtil::ToBool(strRet.c_str(), &bRet);
    return bRet;
}

